Jx.declare('Jx.lib.Engine', {

	$accessors: {

		detect: undefined,

		support: undefined

	},

	$actions: [

		'initialize',

		'construct',

		'destruct',

		'whenReady'

	],

	capable: false,

	ready: false,

	view: undefined,

	readyCallbacks: undefined,

	constructor: function(){

		this.readyCallbacks = [];

		this.detect( this.detect() );

		this.support( this.support() );

		if (!this.detect()){

			throw Jx.createError('Invalid platform detection class');

		} else if (!this.support()){

			throw Jx.createError('Invalid platform support class');

		} else {

			this.$super();

			this.initialize( Jx.GLOBAL );

		}

	},

	onSetDetect: function(operation, Class){

		this.set('detect', Jx.instantiate(Class, operation.arguments || []));

	},

	onSetSupport: function(operation, Class){

		this.set('support', Jx.instantiate(Class, operation.arguments || []));

	},

	onConstruct: function(){

	},

	onAfterConstruct: function(){

		var callbacks = this.readyCallbacks;

		for(var o, l = callbacks.length; l--;){

			o = callbacks[l];

			this.onCallWhenReady(o.callback, o.scope, o.args);

			if (this.isDestroyed()){

				break;

			}

		}

	},

	onDestruct: function(){

	},
	
	onAfterDestruct: function(){
		
		this.destroy();
		
	},

	onWhenReady: function(operation, callback, scope, args){

		operation.scope = scope || undefined;

		operation.args = Jx.isArray(args) ? args : [];

	},

	onAfterWhenReady: function(operation, callback){

		if (!this.ready){

			this.readyCallbacks.unshift({

				callback: callback,

				scope: operation.scope,

				args: operation.args

			});

		} else {

			this.onCallWhenReady(callback, operation.scope, operation.args);

		}

		delete operation.scope;

		delete operation.args;

	},

	onCallWhenReady: function(callback, scope, args){

		callback.apply(scope, args.concat([ this ]));

	},

	allowInitalize: function(operation, GLOBAL){

		return this.capable = this.detect().is('capable');

	},

	allowSetDetect: function(operation, detectClass){

		return Jx.isString(detectClass, true) &&

			Jx.isClass(detectClass, 'Jx.lib.Detect');

	},

	allowSetSupport: function(operation, supportClass){

		var detector;

		operation.arguments = [

			detector = this.detect()

		];

		return !!detector &&

			Jx.isString(supportClass, true) &&

			Jx.isClass(supportClass, 'Jx.lib.Support');

	},

	allowConstruct: function(){

		return this.ready;

	},

	allowWhenReady: function(operation, callback, scope, args){

		return Jx.isFunction(callback);

	}



});
